package tplenguajes.grafo;

import java.util.HashSet;
import java.util.Set;
import java.util.Stack;

public class FiniteAutomata<T> extends DirectedGraph<AutomataState>
{
	private AutomataState root;
	private Set<T> alphabet = null;
	
	public FiniteAutomata(Set<T> alphabet)
	{
		super();
		
		this.alphabet = alphabet;
		
		this.root = new AutomataState();
		addVertex(this.root);
	}
	
	public Set<T> getAlphabet()		{ return alphabet; }
	public AutomataState getRoot()	{ return root; }
	
	public Set<AutomataState> getFinalStates()
	{
		Set<AutomataState> finalStates = new HashSet<AutomataState>();
		
		for ( AutomataState state : getVertices() )
			if ( state.isFinal() )
				finalStates.add(state);
		
		return finalStates;
	}
	
	@Override
	public String toString()
	{
		String str = "digraph G {\n";
		
		str += "node [shape = doublecircle];";
		for ( AutomataState finalState : getFinalStates() )
			str +=  " "+finalState.getId();
		str += ";\n";
		
		str += "node [shape = circle];\n";
		
		str += "\tstart [shape=point,width=\"0\",height=\"0\"];\n";
		str += "\tstart -> "+this.root.getId()+";\n";
		
		Set<AutomataState> visited = new HashSet<AutomataState>();
		Stack<AutomataState> stack = new Stack<AutomataState>();
		
		stack.push(this.root);
		
		while (!stack.empty())
		{
			AutomataState node = stack.pop();
			
			if (!visited.contains(node))
			{
				visited.add(node);
				
				for (Edge<AutomataState> edge : getOutgoingEdges(node))
				{
					AutomataState target = edge.getTarget();
					str += "\t" + node.getId() + " -> " + target.getId() + " [label=\""+ getLabel(edge) +"\"] ;\n";
					
					stack.push(target);
				}
			}
		}
		
		str += "}\n";
		return str;
	}
	
	protected T getLabel(Edge<AutomataState> e) { return ((StateTransition<T>)e).getLabel(); }
	
	protected void print(Set<AutomataState> states)
	{
		System.out.print("{");
		for ( AutomataState state : states )
			System.out.print(state.getId()+" ");
		System.out.print("}\n");
	}
}
